Qt实现IPC进程间通信 您所在的位置:网站首页 macos root权限 跨进程访问 Qt实现IPC进程间通信

Qt实现IPC进程间通信

2024-07-15 10:08| 来源: 网络整理| 查看: 265

Qt实现IPC进程间通信-共享内存方式 1 Qt实现IPC进程间通信-共享内存方式2. 跨进程通信设计:Qt 进程间通讯类全面解析2.1. 引言(Introduction)2.2. 基于共享内存的进程间通信类(Shared Memory-based Interprocess Communication Classes)2.2.1. QSystemSemaphore:用于系统级别的信号量(QSystemSemaphore: For System-Level Semaphores) 2.3.基于消息队列的进程间通信类(Message Queue-based Interprocess Communication Classes)2.4.基于本地套接字的进程间通信类(Local Socket-based Interprocess Communication Classes)2.5. 基于进程启动的进程间通信类(Process Launch-based Interprocess Communication Classes)2.6. 基于 D-Bus 的进程间通信类(D-Bus-based Interprocess Communication Classes) 2.7. 基于远程对象的进程间通信类(Remote Object-based Interprocess Communication Classes)2.8. 综合对比各种方式的优缺点和适用场景以及性能2.9. 从操作系统和 Linux 系统调用的角度分析 Qt 进程间通信类1.共享内存(Shared Memory)与 Linux 系统调用2.消息队列(Message Queue)与 Linux 系统调用3.本地套接字(Local Socket)与 Linux 系统调用4.进程启动(Process Launch)与 Linux 系统调用5. 基于 D-Bus 的进程间通信类与 Linux 系统调用6. 基于远程对象的进程间通信类与 Linux 系统调用7. Qt 进程间通信类的可移植性和跨平台性8. Qt 进程间通信类与系统资源9. Qt 进程间通信类与操作系统权限管理10. Qt 进程间通信类与多线程环境 2.10. Qt 进程间通信类可能出现的异常和解决方案1. 共享内存(Shared Memory)2. 消息队列(Message Queue)3. 本地套接字(Local Socket)4. 进程启动(Process Launch)5. D-Bus6. 远程对象(Remote Objects) 2.11. Qt 进程间通信类综合答疑1. 为什么选择 Qt 进程间通信类?2. 如何选择合适的进程间通信方法?3. 如何处理 Qt 进程间通信过程中的异常?4. 如何优化 Qt 进程间通信性能?5. 如何确保 Qt 进程间通信的安全性?6. 如何避免共享内存数据竞争?7. 如何确保 QLocalServer 和 QLocalSocket 之间的通信顺序?8. 当使用 QProcess 时,如何处理子进程的输出?9. 如何处理 D-Bus 通信中的超时和错误?10. 在使用 QRemoteObjectNode 和 QRemoteObjectHost 时,如何处理网络延迟和丢包? 2.12. 案例分析:不同进程间通信方法在实际项目中的应用1. 共享内存:图像处理应用2. 消息队列:工厂自动化系统3. 本地套接字:桌面应用间通信4. 进程启动:批处理任务调度5. D-Bus:桌面环境组件间通信6. 远程对象:分布式计算应用 2.13.Qt 各版本之间的变化2.14. 从心理学角度的总结 Qt线程/进程间通讯connect函数的第五个参数:Qt进程间数据通讯方法一 共享内存 方法二 socket通信

1 Qt实现IPC进程间通信-共享内存方式

原文链接:https://blog.csdn.net/weixin_40355471/article/details/113176745

QT封装了QSharedMemory类实现共享内存,可以共享文本、图片等各种数据格式,支持windows和linux跨平台使用; 示例代码新建两个工程,分别启动两个应用程序,实现文本数据的共享。

工程A widget_pa.h

#ifndef WIDGET_PA_H #define WIDGET_PA_H #include #include namespace Ui { class Widget_PA; } class Widget_PA : public QWidget { Q_OBJECT public: explicit Widget_PA(QWidget *parent = 0); ~Widget_PA(); void sendStrToMemory(QString str); private slots: void on_pushButton_clicked(); private: Ui::Widget_PA *ui; QSharedMemory m_sharedMemory; }; #endif // WIDGET_PA_H

widget_pa.cpp

#include "widget_pa.h" #include "ui_widget_pa.h" #include #include Widget_PA::Widget_PA(QWidget *parent) : QWidget(parent), ui(new Ui::Widget_PA) { ui->setupUi(this); } Widget_PA::~Widget_PA() { delete ui; } void Widget_PA::sendStrToMemory(QString str) { //1、设置共享内存的标志名 m_sharedMemory.setKey("processAstr"); if(m_sharedMemory.isAttached()) { //2、将该进程与共享内存分离 if(!m_sharedMemory.detach()) { qDebug() sendStrToMemory(ui->textEdit->toPlainText()); }

工程B widget_pb.h

#ifndef WIDGET_PB_H #define WIDGET_PB_H #include #include namespace Ui { class Widget_PB; } class Widget_PB : public QWidget { Q_OBJECT public: explicit Widget_PB(QWidget *parent = 0); ~Widget_PB(); QString loadStrFromMemory(); private slots: void on_pushButton_clicked(); private: Ui::Widget_PB *ui; QSharedMemory m_sharedMemory; }; #endif // WIDGET_PB_H

widget_pb.cpp

#include "widget_pb.h" #include "ui_widget_pb.h" #include #include Widget_PB::Widget_PB(QWidget *parent) : QWidget(parent), ui(new Ui::Widget_PB) { ui->setupUi(this); } Widget_PB::~Widget_PB() { delete ui; } QString Widget_PB::loadStrFromMemory() { //1、设置共享内存的标志名 m_sharedMemory.setKey("processAstr"); //2、将共享内存与该进程绑定 if (!m_sharedMemory.attach()) { qDebug() str; //5、使用完后将共享内存解锁 m_sharedMemory.unlock(); //6、将共享内存与该进程分离 m_sharedMemory.detach(); return str; } void Widget_PB::on_pushButton_clicked() { ui->textEdit->setText(loadStrFromMemory()); }

在这里插入图片描述

2. 跨进程通信设计:Qt 进程间通讯类全面解析

原文链接:https://blog.csdn.net/qq_21438461/article/details/130211974

2.1. 引言(Introduction)

进程间通信的重要性(The Importance of Interprocess Communication) 进程间通信(Interprocess Communication,简称 IPC)是现代软件开发中不可或缺的一部分。在许多应用场景中,多个进程需要共享数据、协同工作,或在不同进程间传递消息。IPC 技术允许这些进程安全、高效地通信,从而实现复杂的功能和任务。

Qt 提供了一系列进程间通信类,以满足各种不同场景和需求。通过掌握这些类,开发者可以在 Qt 应用中实现强大的进程间通信功能。

本文涉及的主题简介(Introduction to the Topics Covered in This Article) 本文将全面介绍 Qt 进程间通信类,包括基于共享内存、消息队列、本地套接字、进程启动、D-Bus 和远程对象的通信类。对于每个类别,我们将介绍相关类的功能和用法,并提供示例代码。最后,我们将总结如何根据应用需求选择合适的进程间通信方法。

2.2. 基于共享内存的进程间通信类(Shared Memory-based Interprocess Communication Classes)

共享内存是一种在不同进程间共享数据的高效方式。通过使用共享内存,多个进程可以访问相同的内存块,从而在进程间直接交换信息。Qt 提供了以下类来实现基于共享内存的进程间通信:

QSharedMemory:用于共享内存(QSharedMemory: For Shared Memory) QSharedMemory 类提供了一个跨进程共享的内存段。它允许不同进程将数据存储在共享内存中,以便其他进程可以访问这些数据。QSharedMemory 使得进程间通信变得快速和简单,但它需要开发者自行处理同步和并发问题。

使用方法:

创建一个 QSharedMemory 实例,指定一个键(key)以唯一标识共享内存段。 使用 create() 方法创建一个共享内存段,或使用 attach() 方法连接到现有的共享内存段。 使用 lock() 方法锁定共享内存,以防止其他进程同时访问。 使用 data() 方法获取共享内存的指针,并对其进行读/写操作。 使用 unlock() 方法解锁共享内存。 使用 detach() 方法从共享内存段断开连接。 示例代码:

#include #include #include // 创建一个共享内存实例,使用唯一的键 "my_shared_memory" QSharedMemory sharedMemory("my_shared_memory"); // 创建一个大小为 1024 字节的共享内存段 if (!sharedMemory.create(1024)) { // 处理错误 } // 锁定共享内存 if (!sharedMemory.lock()) { // 处理错误 } // 写入数据到共享内存 QBuffer buffer; buffer.setBuffer(static_cast(sharedMemory.data())); buffer.open(QIODevice::WriteOnly); QDataStream out(&buffer); out // 处理错误 } // 锁定共享内存 if (!sharedMemory.lock()) { // 处理错误 } // 读取数据从共享内存 QBuffer buffer; buffer.setBuffer(static_cast(sharedMemory.data())); buffer.open(QIODevice::ReadOnly); QDataStream in(&buffer); QString message; in >> message; // 解锁共享内存 sharedMemory.unlock(); // 释放信号量资源 semaphore.release();

这个例子展示了如何使用 QSystemSemaphore 来同步多个进程对共享内存的访问。在这个示例中,一个进程在共享内存中写入数据,而另一个进程从共享内存中读取数据。通过使用 QSystemSemaphore,我们可以确保在读写操作进行时,不会发生数据竞争。

2.3.基于消息队列的进程间通信类(Message Queue-based Interprocess Communication Classes)

QMessageQueue:用于在不同进程之间发送和接收消息(QMessageQueue: For Sending and Receiving Messages between Different Processes) 注意:Qt 并没有提供一个名为 QMessageQueue 的类,但是您可以通过第三方库或自定义实现来使用消息队列。以下内容将介绍一个简单的使用示例。

假设我们已经有一个名为 QMessageQueue 的第三方库或自定义实现,我们可以使用它来进行消息队列通信。以下是如何在不同进程之间发送和接收消息的示例:

发送消息示例:

#include "QMessageQueue" int main(int argc, char *argv[]) { QMessageQueue msgQueue("my_message_queue"); if (!msgQueue.open(QIODevice::WriteOnly)) { // 处理错误 } QByteArray message("Hello, world!"); msgQueue.write(message); msgQueue.close();

接收消息示例:

#include "QMessageQueue" int main(int argc, char *argv[]) { QMessageQueue msgQueue("my_message_queue"); if (!msgQueue.open(QIODevice::ReadOnly)) { // 处理错误 } QByteArray message; msgQueue.read(message); qDebug() QLocalSocket *clientConnection = server.nextPendingConnection(); QObject::connect(clientConnection, &QLocalSocket::disconnected, clientConnection, &QLocalSocket::deleteLater); clientConnection->write("Hello, client!"); clientConnection->flush(); clientConnection->disconnectFromServer(); }); if (!server.listen("my_local_socket")) { // 处理错误 } return a.exec();

客户端代码:

#include #include int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QLocalSocket socket; socket.connectToServer("my_local_socket"); if (socket.waitForConnected()) { socket.waitForReadyRead(); qDebug() QCoreApplication a(argc, argv); QProcess process; QObject::connect(&process, &QProcess::readyReadStandardOutput, [&process] { qDebug() QCoreApplication a(argc, argv); QDBusConnection connection = QDBusConnection::sessionBus(); if (!connection.isConnected()) { qCritical() qCritical() QCoreApplication a(argc, argv); QRemoteObjectNode node; node.connectToNode(QUrl("local:remote_object")); QSharedPointer replica = node.acquire(); if (!replica->waitForSource()) { qCritical() unsigned char data1[4]; int data2; double data3; ... }MYSTRUCT; ------------------------------------------------------------------ //mainwindow.h ... //表示无关代码shenglve #include "testthread.h" #include "mystruct.h" #include class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); void init(); public slots: void slot_receive(const MYSTRUCT mystruct) private: TestThread *m_testThread; ... } ------------------------------------------------------------------ //mainwindow.cpp ... MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { init(); } void Mainwindow::init() { qRegisterMetaType("mystruct"); //MYSTRUCT 为自定义数据类型 //mystruct 为定义的名称 m_testThread = new TestThread(); connect(m_testThread, &TestThread::signal_send, this, &Mainwindow::slot_receive); m_testThread->start(); } void Mainwindow::slot_receive(const MYSTRUCT mystruct) { } ... ------------------------------------------------------------------ //testthread.h #include "mystruct.h" ... class TestThread : public QThread { Q_OBJECT public: TestThread(); virtual void run(); signals: void signal_send(const MYSTRUCT mystruct); private: MYSTRUCT m_struct; ... } ------------------------------------------------------------------ //testthread.cpp ... TestThread::TestThread() { m_struct.data1[0] = 1; m_struct.data1[1] = 1; m_struct.data1[2] = 1; m_struct.data1[3] = 1; m_struct.data2 = 2; m_struct.data3 = 3.0; } void run() { while(1) { emit signal_send(m_struct); sleep(1000); } }

上述例程中线程使用 run() 方式运行,还可以使用 movetothread()(各路大佬推荐使用)方式运行;

线程间用信号槽传递参数的话,要加const,因为const文字常量存在常量区中,生命周期和程序一样长,可以避免slot调用的时候参数的运行期已过造成引用无效;

connect函数的第五个参数:

(1) Qt::AutoConnection 如果发射信号的线程和执行槽函数的线程是同一个线程,此时等同于Qt::DirectConnection;如果不在同一个线程,就等同于Qt::QueuedConnection,是connect函数的默认参数; (2) Qt::DirectConnection 发射信号和执行槽函数由同一个线程(信号发射的线程)完成,信号发射后槽函数立马执行,执行完毕后才继续执行“emit信号”后面的代码,即“emit信号”是阻塞的; (3) Qt::QueuedConnection 发射信号的线程和执行槽函数的线程不是在同一个线程,此时发射信号的线程不阻塞,马上返回,当执行槽函数的线程被CPU调度时,就会执行槽函数; (4) Qt::BlockingQueuedConnection 和Qt::QueuedConnection基本一样,只是发射信号的线程会被阻塞,直到槽函数被执行完毕,如果使用这个属性,需确保发射信号的线程与执行槽函数的线程不同,否则将发生死锁; (5) Qt::UniqueConnection 唯一关联,该类型可以和上面的类型通过“|”符号配合使用,同一个信号与同一个槽只能调用connect一次,不能多次调用;

Qt进程间数据通讯 方法一 共享内存

原理:两个个进程共用同一片物理内存 实现方式如下:

进程A(数据写入)

//processA.h #include class ProcessA { ... public: ProcessA(); ~ProcessA(); void writeButtonClicked(); private: QSharedMemory *m_shareMemory; ... } ... --------------------------------------------------------- //processA.cpp ... ProcessA::ProcessA() { ... m_shareMemory = new QSharedMemory(); //实例化QSharedMemory类 m_shareMemory->setKey("TestKey"); //通过setKey()设置标签名称; //判断当前实例化对象m_shareMemory是否已经与进程连接,如果已经连接,使用函数detach()将与进程分离。 if(m_shareMemory->isAttached()) { m_shareMemory->detach(); } //使用函数create()创建共享内存段,判断是否创建成功,若失败,打印错误信息并返回 if(!m_shareMemory->create(50)) { qDebug() char testStr[50] = "This is my share memory!"; m_shareMemory->lock(); //使用共享内存前需调用lock()将共享内存上锁 char *destination = reinterpret_cast(m_shareMemory->data()); const char *source = testStr; memcpy(destination, source, 50); //将数据写入共享内存 m_shareMemory->unlock(); //调用unlock()函数解锁 }

进程B(读取写入)

//processB.h #include class ProcessB { ... public: ProcessB(); ~ProcessB(); void readButtonClicked(); private: QSharedMemory *m_shareMemory; ... } ... --------------------------------------------------------- //processB.cpp ... ProcessB::ProcessB() { ... m_shareMemory = new QSharedMemory(); //实例化QSharedMemory类 m_shareMemory->setKey("TestKey"); //通过函数setKey()设置标签名称; //连接共享内存与进程 if(!m_shareMemory->attach()) { qDebug() char testStr[50]; m_shareMemory->lock(); //使用共享内存前需调用lock()将共享内存上锁 const char *source = (char*)m_shareMemory->constData(); char *destination = testStr; memcpy(destination, source, 50); //从共享内存里读取数据 m_shareMemory->unlock(); //调用unlock()函数解锁 } 方法二 socket通信

在两个进程之间创建socket,自己定义一套通信协议,通过socket,实现两个进程间的数据传输,在此不做赘述,可以参考socket通信相关内容。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有